package db

import (
	"database/sql/driver"
	"encoding/json"
	"errors"
	"fmt"
	"gorm.io/gorm"
	"gorm.io/plugin/soft_delete"
	"strings"
	"time"
)

type Student struct {
	ID     uint    `gorm:"size:3"`
	Name   string  `gorm:"size:32"`
	Age    int     `gorm:"size:3"`
	Gender string  `gorm:"size:2"`
	Email  *string `gorm:"size:32"`
}

func (s *Student) BeforeCreate(tx *gorm.DB) (err error) {
	if s.Email == nil {
		email := "test@test.com"
		s.Email = &email
	}
	return nil
}

type StudentBaseInfo struct {
	Name string
	Age  int
}

type Test struct {
	Hasd string `gorm:"column:name"`
	Age  int
}

type GenderCount struct {
	Count  int
	Gender string
	Name   string
}

type User struct {
	ID        uint
	Name      string `gorm:"size:32"`
	Articles  []Article
	UserInfo  UserInfo
	DeletedAt *time.Time
	IsDel     soft_delete.DeletedAt `gorm:"softDelete:flag,DeletedAtField:DeletedAt"`
}

type UserInfo struct {
	UserID    uint
	ID        uint
	Like      string `gorm:"size:256"`
	Addr      string `gorm:"size:128"`
	DeletedAt *time.Time
	IsDel     soft_delete.DeletedAt `gorm:"softDelete:flag,DeletedAtField:DeletedAt"`
}

type Article struct {
	ID      uint
	Title   string `gorm:"size:32"`
	Content string
	UserID  uint
	User    User
	Tags    []Tag `gorm:"many2many:article_tags"`
}

type Tag struct {
	ID       uint
	Name     string
	Articles []Article `gorm:"many2many:article_tags"`
}

type Person struct {
	ID        int
	Name      string
	Addresses []Address `gorm:"many2many:person_addresses;"`
}

type Address struct {
	ID   uint
	Name string
}

type PersonAddress struct {
	PersonID  int `gorm:"primaryKey"`
	AddressID int `gorm:"primaryKey"`
	CreatedAt time.Time
	UpdatedAt time.Time
}

//func (pa *PersonAddress) BeforeCreate(db *gorm.DB) error {
//	pa.CreatedAt = time.Now()
//	return nil
//}

type ArticleModel struct {
	ID    uint
	Title string
	Tags  []TagModel `gorm:"many2many:article_tags;joinForeignKey:ArticleID;joinReferences:TagID"`
}

type TagModel struct {
	ID   uint
	Name string
	//Articles []ArticleModel `gorm:"many2many:article_tags;joinForeignKey:TagID;joinReferences:ArticleID"`
}

type ArticleTagModel struct {
	ArticleID uint `gorm:"primaryKey"`
	TagID     uint `gorm:"primaryKey"`
	CreatedAt time.Time
}

type UserModel struct {
	ID       uint
	Name     string
	Collects []ArticleModel `gorm:"many2many:user_collects;joinForeignKey:UserID;joinReferences:ArticleID"`
}

type UserCollectModel struct {
	UserID    uint         `gorm:"primaryKey"`
	User      UserModel    `gorm:"foreignKey:UserID"`
	ArticleID uint         `gorm:"primaryKey"`
	Article   ArticleModel `gorm:"foreignKey:ArticleID"`
	CreatedAt time.Time
}

type AuthModel struct {
	ID   uint
	Name string
	Info Info `gorm:"type:string"`
}

type Info struct {
	Address string
	Age     int
	Like    string
}

func (i Info) Value() (driver.Value, error) {
	return json.Marshal(i)
}

func (i *Info) Scan(value any) error {
	b, ok := value.([]byte)
	if !ok {
		return errors.New(fmt.Sprintf("Failed to unmarshal JSON value: %v", value))
	}
	err := json.Unmarshal(b, i)
	return err
}

type HostModel struct {
	ID     uint
	IP     string
	Status Status `gorm:"size:8"`
	Post   Array
}

type Array []string

func (a Array) Value() (driver.Value, error) {
	return strings.Join(a, ";"), nil
}

func (a *Array) Scan(value any) error {
	data, ok := value.([]byte)
	if !ok {
		return errors.New(fmt.Sprintf("解析失败: %v %T", value, value))
	}
	*a = strings.Split(string(data), ";")
	return nil
}
